package com.lottery.shadowbd.io.http;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.lottery.shadowbd.callback.Callback;
import com.lottery.shadowbd.callback.OnDownloadListener;
import com.lottery.shadowbd.support.ThreadPoolKit;
import com.lottery.shadowbd.tuple.Tuple2;
import com.lottery.shadowbd.utils.LogUtils;

import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Dispatcher;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by han on 2017/5/19 0019.
 */
public class OkHttpIO {
    static volatile OkHttpIO instance;
    private Handler handler;
    public OkHttpClient okHttpClient;

    static public OkHttpIO getInstance() {
        if (instance == null) {
            synchronized (OkHttpIO.class) {
                if (instance == null) {
                    instance = new OkHttpIO();
                }
            }
        }
        return instance;
    }

    public OkHttpIO() {
        this.handler = new Handler(Looper.getMainLooper());
        //配置 client
        Dispatcher dispatcher = new Dispatcher(ThreadPoolKit.createThreadPoolExecutor(1, 12, 60l, TimeUnit.SECONDS, "app-http"));
        //最大并发访问
        dispatcher.setMaxRequests(10);
        this.okHttpClient = new OkHttpClient.Builder()
                .dispatcher(dispatcher)
                .build();
    }

    /**
     * 发起 GET 请求
     *
     * @param url
     * @param callback
     */
    public void get(@NonNull String url, @Nullable final Callback<Tuple2<Integer, String>, Exception> callback) {
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();

        okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final int code = response.code();
                final String string = response.body().string();
                if (callback != null) {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onSuccess(new Tuple2<Integer, String>(code, string));
                        }
                    });
                }
            }

            @Override
            public void onFailure(Call call, final IOException e) {
                if (callback != null) {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onError(e);
                        }
                    });
                }
            }
        });
    }

    /**
     * 发起 GET 请求
     *
     * @param url
     * @return
     */
    public Call get(@NonNull String url) {
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        return okHttpClient.newCall(request);
    }

    /**
     * 发起 POST
     *
     * @param url
     * @param requestBody
     * @param callback
     */
    public void post(@NonNull String url, @Nullable RequestBody requestBody, @Nullable final Callback<Tuple2<Integer, String>, Exception> callback) {
        //如果请求的数据为空，则给定一个空的表单，进行提交
        if (requestBody == null) {
            requestBody = new FormBody.Builder().build();
        }
        //构造请求
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final int code = response.code();
                final String string = response.body().string();

                LogUtils.e("---请求返回码：" + code);

                if (callback != null) {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onSuccess(new Tuple2<Integer, String>(code, string));
                        }
                    });
                }
            }

            @Override
            public void onFailure(Call call, final IOException e) {
                if (callback != null) {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onError(e);
                        }
                    });
                }
            }

        });
    }

    /**
     * 发起 POST
     *
     * @param url
     * @param callback
     */
    public void getTrendAsny(@NonNull String url, @Nullable final Callback<Tuple2<Integer, InputStream>, Exception> callback) {
        Request request = new Request.Builder()
                .url(url)
                .build();
        okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                System.out.println();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                InputStream inputStream = response.body().byteStream();
                final int code = response.code();
                callback.onSuccess(new Tuple2<Integer, InputStream>(code, inputStream));
            }
        });
    }

    /**
     * 发起 POST
     *
     * @param url
     * @param requestBody
     * @return
     */
    public Call post(@NonNull String url, @Nullable RequestBody requestBody) {
        //如果请求的数据为空，则给定一个空的表单，进行提交
        if (requestBody == null) {
            requestBody = new FormBody.Builder().build();
        }
        //构造请求
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        return okHttpClient.newCall(request);
    }

    /**
     * 文件下载
     *
     * @param url              下载连接
     * @param savePath         储存下载文件的SDCard目录
     * @param downloadListener 下载监听
     */
    public void postDownload(@NonNull String url, @NonNull final String savePath, @NonNull final String saveName, @Nullable final OnDownloadListener downloadListener) {
        //构造请求
        Request request = new Request.Builder()
                .url(url)
                .build();
        okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final int code = response.code();

                LogUtils.e("---想问请求返回码：" + code);

                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;

                try {
                    is = response.body().byteStream();
                    long total = response.body().contentLength();
                    File file = new File(savePath, saveName);
                    fos = new FileOutputStream(file);
                    long sum = 0;

                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                        sum += len;

                        // 下载中
                        downloadListener.onDownloading(total, sum);
                    }

                    fos.flush();

                    // 下载完成
                    downloadListener.onDownloadSuccess();
                } catch (Exception e) {
                    downloadListener.onDownloadFailed(e);
                } finally {
                    try {
                        if (is != null)
                            is.close();
                    } catch (IOException e) {
                    }
                    try {
                        if (fos != null)
                            fos.close();
                    } catch (IOException e) {
                    }
                }
            }

            @Override
            public void onFailure(Call call, IOException e) {
                if (downloadListener != null) {
                    downloadListener.onDownloadFailed(e);
                }
            }
        });
    }
}
